package cn.ctodb.service;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.inject.Inject;
import javax.mail.internet.MimeMessage;

import org.apache.commons.lang.CharEncoding;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import cn.ctodb.config.JHipsterProperties;
import cn.ctodb.domain.User;
import freemarker.template.Template;

/**
 * Service for sending e-mails.
 * <p>
 * We use the @Async annotation to send e-mails asynchronously.
 * </p>
 */
@Service
public class SysMailService {

    private final Logger         log      = LoggerFactory.getLogger(SysMailService.class);

    private static final String  USER     = "user";
    private static final String  BASE_URL = "baseUrl";

    @Inject
    private JHipsterProperties   jHipsterProperties;

    @Inject
    private JavaMailSenderImpl   javaMailSender;

    @Inject
    private MessageSource        messageSource;

    @Inject
    private FreeMarkerConfigurer configurer;

    @Async
    public void sendEmail(String to, String subject, String content, boolean isMultipart, boolean isHtml) {
        log.debug("Send e-mail[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}", isMultipart, isHtml, to, subject, content);

        // Prepare message using a Spring helper
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        try {
            MimeMessageHelper message = new MimeMessageHelper(mimeMessage, isMultipart, CharEncoding.UTF_8);
            message.setTo(to);
            message.setFrom(jHipsterProperties.getMail().getFrom());
            message.setSubject(subject);
            message.setText(content, isHtml);
            javaMailSender.send(mimeMessage);
            log.debug("Sent e-mail to User '{}'", to);
        } catch (Exception e) {
            log.warn("E-mail could not be sent to user '{}', exception is: {}", to, e.getMessage());
        }
    }

    @Async
    public void sendActivationEmail(User user, String baseUrl) {
        try {
            log.debug("Sending activation e-mail to '{}'", user.getEmail());
            Locale locale = Locale.forLanguageTag(user.getLangKey());
            Template tpl = configurer.getConfiguration().getTemplate("activationEmail", locale);
            Map<String, Object> context = new HashMap<>();
            context.put(USER, user);
            context.put(BASE_URL, baseUrl);
            String content = FreeMarkerTemplateUtils.processTemplateIntoString(tpl, context);
            String subject = messageSource.getMessage("email.activation.title", null, locale);
            sendEmail(user.getEmail(), subject, content, false, true);
        } catch (Exception e) {
            log.error("", e);
        }
    }

    @Async
    public void sendCreationEmail(User user, String baseUrl) {
        try {
            log.debug("Sending creation e-mail to '{}'", user.getEmail());
            Locale locale = Locale.forLanguageTag(user.getLangKey());
            Template tpl = configurer.getConfiguration().getTemplate("creationEmail", locale);
            Map<String, Object> context = new HashMap<>();
            context.put(USER, user);
            context.put(BASE_URL, baseUrl);
            String content = FreeMarkerTemplateUtils.processTemplateIntoString(tpl, context);
            String subject = messageSource.getMessage("email.activation.title", null, locale);
            sendEmail(user.getEmail(), subject, content, false, true);
        } catch (Exception e) {
            log.error("", e);
        }
    }

    @Async
    public void sendPasswordResetMail(User user, String baseUrl) {
        try {
            log.debug("Sending password reset e-mail to '{}'", user.getEmail());
            Locale locale = Locale.forLanguageTag(user.getLangKey());
            Template tpl = configurer.getConfiguration().getTemplate("passwordResetEmail", locale);
            Map<String, Object> context = new HashMap<>();
            context.put(USER, user);
            context.put(BASE_URL, baseUrl);
            String content = FreeMarkerTemplateUtils.processTemplateIntoString(tpl, context);
            String subject = messageSource.getMessage("email.reset.title", null, locale);
            sendEmail(user.getEmail(), subject, content, false, true);
        } catch (Exception e) {
            log.error("", e);
        }
    }

}
